package org.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.stereotype.Compenent;

import java.util.Set;

/**
 * @Name ClassPathBeanDefinitionScanner
 * @Description: 包 @Component 注解扫描器
 * 描述信息：解析 <context:component-scan /> 标签，扫描指定包中 @Component 注解的类，提取类信息，组装成 BeanDefinition。
 * @Version v1.0.0
 * @Author: lichao
 * @Date: 2024-04-09 16:24:55
 **/
public class ClassPathBeanDefinitionScanner extends ClasspathScanningCandidateComponentProvider {
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                // 解析 @Scope 注解的作用域
                String scope = resolveBeanScope(candidate);
                if (StrUtil.isNotEmpty(scope)) {
                    candidate.setScope(scope);
                }
                // 生成 Bean 实例名称
                String beanName = determineBeanName(candidate);
                // 注册 BeanDefinition 信息
                registry.registerBeanDefinition(beanName, candidate);
            }
        }
        // 注册处理 @Autowired 和 @Value 注解的 BeanPostProcessor
        registry.registerBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    /**
     * 解析 @Scope 注解的作用域
     *
     * @param beanDefinition BeanDefinition 信息
     * @return java.lang.String 结果
     * @version v1.0.0
     * @author lichao
     * @date 2024-04-09 16:38:42
     */
    private String resolveBeanScope(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if (scope != null) return scope.value();
        return StrUtil.EMPTY;
    }

    /**
     * 解析 @Compenent 注解的 Bean 实例名称
     *
     * @param beanDefinition BeanDefinition 信息
     * @return java.lang.String 结果
     * @version v1.0.0
     * @author lichao
     * @date 2024-04-09 16:41:05
     */
    private String determineBeanName(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Compenent compenent = beanClass.getAnnotation(Compenent.class);
        String value = compenent.value();
        if (StrUtil.isEmpty(value)) {
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }

}

